package stdx;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class TaskQueue{
    public static class WorkItem implements Runnable{
        long etime = 0;
        Runnable item = null;

        public void run(){
            if (item != null) item.run();
        }
        public boolean runnable(){
            if (etime <= 0 || System.currentTimeMillis() > etime) return true;

            Utils.Sleep(1);

            return false;
        }
        public void setDelay(long delay){
            etime = delay > 0 ? System.currentTimeMillis() + delay * 1000 : 0;
        }
        WorkItem(Runnable item, long delay){
            this.setDelay(delay);
            this.item = item;
        }
    }

    BlockingQueue<Runnable> queue = null;
    static TaskQueue taskqueue = new TaskQueue();

    public void start(int threads){
        if (queue == null) queue = new LinkedBlockingQueue<Runnable>();

        while (threads-- > 0){
            new Thread(){
                public void run(){
                    while (true){
                        try{
                            Runnable item = queue.take();

                            if (item instanceof WorkItem){
                                if (((WorkItem)(item)).runnable()){
                                    item.run();
                                }
                                else{
                                    queue.add(item);
                                }
                            }
                            else {
                                item.run();
                            }
                        }
                        catch(Exception e){
                            e.printStackTrace();

                            Utils.Sleep(10);
                        }
                    }
                }
            }.start();
        }
    }
    public boolean push(Runnable task){
        return push(task, 0);
    }
    public boolean push(Runnable task, long delay){
        if (task == null) return false;

        if (queue == null) start(4);

        try{
            if (delay > 0) task = new WorkItem(task, delay);

            queue.put(task);

            return true;
        }
        catch(Exception e){
            return false;
        }
    }
    public static TaskQueue Instance(){
        return taskqueue;
    }
}
